package com.siyu.common.utils.aliyun.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.siyu.common.config.aliyun.OssConfig;
import com.siyu.common.config.aliyun.OssConfigProperties;
import com.siyu.common.utils.aliyun.service.FileOssStorageService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.io.*;


@EnableConfigurationProperties(OssConfigProperties.class)
@Import(OssConfig.class)
@Component
public class OssFileStorageService implements FileOssStorageService {

    private static final Logger log = LoggerFactory.getLogger(OssFileStorageService.class);
    private static final String separator = "/";

    @Autowired
    private OSS ossClient;
    @Autowired
    private OssConfigProperties ossConfigProperties;

    /**
     * 构建文件路径
     * @param dirPath 目录路径
     * @param filename 文件名
     * @return 文件全路径
     */
    public String builderFilePath(String dirPath, String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        if (!StringUtils.isEmpty(dirPath)) {
            stringBuilder.append(dirPath).append(separator);
        }
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }

    /**
     * 上传图片文件
     * @param prefix 文件前缀
     * @param filename 文件名
     * @param localfilename 本地文件名
     * @return 文件全路径
     */
    public String uploadJsonFile(String prefix, String filename, String localfilename) {
        String filePath = builderFilePath(prefix, filename);
        try {
            ossClient.putObject(ossConfigProperties.getBucketname(), filePath, new File(localfilename));

            StringBuilder urlPath = new StringBuilder(ossConfigProperties.getHttpsprefix());
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception ex) {
            log.error("OSS put file error.", ex);
            throw new RuntimeException("上传文件失败");
        }
    }


    /**
     * 上传word文件
     * @param prefix 文件前缀
     * @param filename 文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    public String uploadWordFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        String extension = filename.substring(filename.lastIndexOf('.') + 1);
        String contentType = determineContentType(extension);

        byte[] fileBytes;
        try {
            fileBytes = IOUtils.toByteArray(inputStream);
        } catch (IOException e) {
            log.error("Error reading input stream for HTML file: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to read input stream", e);
        }

        try {
            // 创建OSSObjectMetadata对象并设置content-type
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(contentType);

            // 上传文件
            ossClient.putObject(ossConfigProperties.getBucketname(), filePath, new ByteArrayInputStream(fileBytes), metadata);

            StringBuilder urlPath = new StringBuilder(ossConfigProperties.getHttpsprefix());
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (OSSException ex) {
            log.error("Error uploading file to OSS: {}", ex.getMessage(), ex);
            throw new RuntimeException("Failed to upload file", ex);
        }
    }

    private String determineContentType(String extension) {
        switch (extension) {
            case "doc":
                return "application/msword";
            case "docx":
                return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "pdf":
                return "application/pdf";
            case "geojson":
                return "application/geo+json";
            default:
                throw new IllegalArgumentException("Unsupported file type: " + extension);
        }
    }

    /**
     * 删除文件
     * @param pathUrl 文件全路径
     */
    public void delete(String pathUrl) {
        String key = pathUrl.replace(ossConfigProperties.getHttpsprefix(), "");
        ossClient.deleteObject(ossConfigProperties.getBucketname(), key);
    }

    /**
     * 下载文件
     * @param pathUrl 文件全路径
     * @return 文件字节数组
     */
    public byte[] downLoadFile(String pathUrl) {
        String key = pathUrl.replace(ossConfigProperties.getHttpsprefix(), "");
        OSSObject ossObject = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {
            // 获取文件的输入流
            // 获取文件的OSSObject
            ossObject = ossClient.getObject(ossConfigProperties.getBucketname(), key);

            // 获取OSSObject的输入流
            inputStream = ossObject.getObjectContent();

            // 将输入流转换为字节数组
            byteArrayOutputStream = new ByteArrayOutputStream();
            IOUtils.copy(inputStream, byteArrayOutputStream);

            return byteArrayOutputStream.toByteArray();
        } catch (OSSException | IOException e) {
            log.error("OSS download file error. pathUrl:{}", pathUrl, e);
            throw new RuntimeException("Failed to download file", e);
        } finally {
            // 关闭输入流
            IOUtils.closeQuietly(inputStream);
            // 关闭字节输出流
            IOUtils.closeQuietly(byteArrayOutputStream);
        }
    }


    /**
     * 上传GeoJSON文件
     * @param prefix 前缀
     * @param filename 文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    public String uploadGeoJsonFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        String extension = filename.substring(filename.lastIndexOf('.') + 1);
        String contentType = determineContentType(extension);

        byte[] fileBytes;
        try {
            fileBytes = IOUtils.toByteArray(inputStream);
        } catch (IOException e) {
            log.error("Error reading input stream for GeoJSON file: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to read input stream", e);
        }

        try {
            // 创建OSSObjectMetadata对象并设置content-type

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(contentType);

            // 上传文件
            ossClient.putObject(ossConfigProperties.getBucketname(), filePath, new ByteArrayInputStream(fileBytes), metadata);


            StringBuilder urlPath = new StringBuilder(ossConfigProperties.getHttpsprefix());
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (OSSException ex) {
            log.error("Error uploading file to OSS: {}", ex.getMessage(), ex);
            throw new RuntimeException("Failed to upload file", ex);
        }
    }
}